package com.example.adminserivce.Service.Impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.adminserivce.Mapper.WeeklyActivityMapper;
import com.example.adminserivce.Service.ActivityService;
import com.example.adminserivce.Service.UserService;
import com.example.adminserivce.Service.WeekScheduleService;
import com.example.common.constants.OtherConstants;
import com.example.common.constants.RdsConstants;
import com.example.common.constants.RoleConstants;
import com.example.common.domain.pojo.WeeklyActivity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.DayOfWeek;
import java.time.LocalDate;

@Service
@Slf4j
public class WeekScheduleServiceImpl extends ServiceImpl<WeeklyActivityMapper, WeeklyActivity> implements WeekScheduleService {
    // 基准日期：2025-05-20 为第一周起始日
    private static final LocalDate BASE_DATE = LocalDate.of(OtherConstants.ACTIVE_YEAR,
            OtherConstants.ACTIVE_MONTH, OtherConstants.ACTIVE_DAY);//年，月，日
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private ActivityService activityService;
    @Autowired
    private UserService userService;

    // 每月1日凌晨执行：清理旧的周数据
    @Scheduled(cron = "0 0 0 1 * ?")
    public void cleanOldWeeklyData() {
        LocalDate now = LocalDate.now();
        log.info("现在 {} 开始清除旧的周活跃数据", now);
        int currentWeek = activityService.calculateWeekNumber(now); // 调用Service方法计算周次
        // 保留最近12周数据
        int minWeekToKeep = currentWeek - OtherConstants.ACTIVE_WEEK_NUMBER;
        // 删除 Redis 中小于 minWeekToKeep 的周数据
//        redisTemplate.keys("*:week:[0-9]*").forEach(key -> {
        redisTemplate.keys(OtherConstants.MIN_WEEK_TO_KEEP).forEach(key -> {
            int weekNumber = Integer.parseInt(key.split(":")[2]);
            if (weekNumber < minWeekToKeep) {
                redisTemplate.delete(key);
            }
        });
        log.info("现在 {} 清除旧的周活跃数据完成", now);
    }

    // 每周一凌晨执行：将上周数据持久化到数据库
    @Scheduled(cron = "0 0 0 * * MON")
    @Transactional
    public void syncWeeklyDataToDB() {
        LocalDate lastMonday = LocalDate.now()
                .with(java.time.temporal.TemporalAdjusters.previous(DayOfWeek.MONDAY));
        log.info("现在 {} 开始同步周活跃数据到数据库", lastMonday);
        int weekNumber = activityService.calculateWeekNumber(lastMonday);
        // 同步教师数据
        syncUserTypeToDB(RoleConstants.TEACHER, weekNumber);
        log.info("现在 {} 同步教师周活跃数据到数据库完成", lastMonday);
        // 同步学生数据
        syncUserTypeToDB(RoleConstants.STUDENT, weekNumber);
        log.info("现在 {} 同步学生周活跃数据到数据库完成", lastMonday);
    }

    private void syncUserTypeToDB(String userType, int weekNumber) {
        // 1. 获取周活跃用户数
//        String activeKey = String.format("%s:active:week:%d", userType, weekNumber);
        String activeKey = String.format(RdsConstants.WEEKLY_ACTIVE_KEY, userType, weekNumber);
        Long activeCount = redisTemplate.opsForHyperLogLog().size(activeKey);

        // 2. 获取总用户数
        Long totalCount = userType.equals(RoleConstants.TEACHER)
                ? userService.getTotalTeacherCount()
                : userService.getTotalStudentCount();

        // 3. 计算活跃百分比
        double activePercentage = activityService.calculatePercentage(activeCount, totalCount);
        // 4. 构建实体并保存到数据库
        WeeklyActivity entity = new WeeklyActivity();
        entity.setUserType(userType);
        entity.setSyncDate(LocalDate.now());       //同步数据时间
        entity.setWeekNumber(weekNumber);
        entity.setActiveCount(activeCount);
        entity.setTotalCount(totalCount);
        entity.setActivePercentage(activePercentage);
        entity.setWeekStartDate(BASE_DATE.plusWeeks(weekNumber - 1));  //同步的哪一种时间
        this.save(entity);
    }

}
